/*
 * HTMLLexer.cpp
 *
 *  Created on: 2010-5-2
 *      Author: Guobc
 */

#include "HTMLLexer.h"
#include <cctype>
using namespace HA;

HTMLLexer::HTMLLexer(string name) :
	HA::Lexer(name), mLine(0) {
}

Token* HTMLLexer::fetchToken() throw (ParserException) {
	try {
		string line = "";
		bool isPartOfSymbol = true;
		char ch;
		while (fin.good()) {
			fin.get(ch);
			switch (ch) {
			case '<':
				return newToken("<", tOAglBkt);
			case '!':
				return newToken("!", tExcmtMak);
			case '/':
				return newToken("/", tSlash);
			case '>':
				return newToken(">", tCAglBkt);
			case '-':
				line += ch;
				//Lookahead for one byte
				fin.get(ch);
				switch (ch) {
				case '-':
					return newToken("--", tDoubleHyphen);
				default:
					line += ch;
				}
				break;
			case '=':
				return newToken("=", tAssignment);
			case '%':
				line.push_back(ch);
//				//lookahead for one byte
				fin.get(ch);
				switch (ch) {
				case '@':
				case '=':
					line.push_back(ch);
					break;
				default:
					fin.seekg(-1, ios_base::cur);//back up on byte;
					break;
				}
				return newToken(line, tJSP);
			case '\''://skip double quotation string in the single quotation
				line += ch;
				while (fin.good()) {
					fin.get(ch);
					line += ch;
					if (ch == '\'') {
						break;
					}
					if (ch == '<') {
						fin.seekg(-1, ios_base::cur);//back up on byte;
//						throw ParserException(__FUNCTION__, __LINE__,
//								"HTMLLexer");
						break;
					}
				}
				return newToken(line, tQuotationString);
			case '\"':
				line += ch;
				while (fin.good()) {
					fin.get(ch);
					line += ch;
					if (ch == '\"') {
						break;
					}
					if (ch == '<') {
						fin.seekg(-1, ios_base::cur);//back up on byte;
//						throw ParserException(__FUNCTION__, __LINE__,
//								"HTMLLexer");
						break;
					}
				}
				return newToken(line, tQuotationString);
				//			case '&':
				//				line += ch;
				//				while (fin.good()) {
				//					line += ch;
				//					if (ch == '#') {
				//						type_char = tCharacterEntityCode;
				//					}
				//					if (ch == ';') {
				//						break;
				//					}
				//					if (ch == ' ' || ch == '<') {
				//						throw ParserException(__FUNCTION__, __LINE__, "HTMLLexer");
				//						break;
				//					}
				//				}
				//				return newToken("&", type_char);
			case ' ':
			case '\t':
			case 0xb:
			case '\f':
			case '\r':
			case '\n':
				line.push_back(ch);
				if(ch == '\n' || ch == '\r'){
					mLine++;
				}
				while (fin.good()) {
					fin.get(ch);
					if (!isspace(ch)) {
						fin.seekg(-1, ios_base::cur);
						break;
					}
					line.push_back(ch);
				}
				return newToken(line, tWhiteSpace);
			default:
				//			case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
				//			case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
				//			case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
				//			case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B':
				//			case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I':
				//			case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
				//			case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W':
				//			case 'X': case 'Y': case 'Z':
				//			case '_': case '.': case ':':
				line += ch;
				while (fin.good()) {
					fin.get(ch);
					switch (ch) {
					case ' ':
					case '\t':
					case 0xb:
					case '\f':
					case '\r':
					case '\n':
					case '<':
					case '>':
					case '=':
//					case '!':
						isPartOfSymbol = false;
						fin.seekg(-1, ios_base::cur);//back up on byte;
						break;
					default:
						line += ch;
					}
					if (!isPartOfSymbol)
						break;
				}
				return newToken(line, tSymbol);
				//			case '0': case '1': case '2': case '3': case '4': case '5':
				//			case '6': case '7': case '8': case '9':
				//				line += ch;
				//				while (fin.good()) {
				//					fin.get(ch);
				//					switch (ch) {
				//					case ' ': case '\t': case 0xb: case '\f': case '\r': case '\n':
				//						isPartOfNumber = false;
				//						break;
				//					case ';':
				//						isPartOfNumber = false;
				//						fin.seekg(-1, ios_base::cur);//back up on byte;
				//						break;
				//					default:
				//						line += ch;
				//					}
				//					if (!isPartOfNumber)
				//						break;
				//				}
				//				return newToken(line, tNumber);
			}
		}

	} catch (...) {
		throw ParserException(__FUNCTION__, __LINE__, "HTMLLexer");
	}
	return NULL;
}

Token* HTMLLexer::newToken(string line, int type) {
	Token* token = new Token();
	token->setLine(mLine);
	token->setOffset(fin.gcount() - line.length());
	token->setText(line);
	token->setType(type);
	return token;
}

int HTMLLexer::getPosition() {
	if (fin.good()) {
		return fin.gcount();
	}
	return -1;
}
